package cau.se.project.view;

import java.util.List;

import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point;

import cau.se.project.data.method.GroupControl;
import cau.se.project.data.method.RowControl;
import de.kupzog.ktable.KTableCellEditor;
import de.kupzog.ktable.KTableCellRenderer;
import de.kupzog.ktable.KTableDefaultModel;
import de.kupzog.ktable.SWTX;
import de.kupzog.ktable.editors.KTableCellEditorCheckbox;
import de.kupzog.ktable.renderers.CheckableCellRenderer;
import de.kupzog.ktable.renderers.DefaultCellRenderer;
import de.kupzog.ktable.renderers.TextCellRenderer;

public class DSMTableModel extends KTableDefaultModel {

	private int[][] depArray = null;
	private List<RowControl> arrayList = null;
	private TextCellRenderer rowHeadRenderer = new TextCellRenderer(TextCellRenderer.INDICATION_FOCUS_ROW | TextCellRenderer.INDICATION_FOCUS);
	private TextCellRenderer groupRowHeadRenderer = new TextCellRenderer(TextCellRenderer.INDICATION_FOCUS_ROW | TextCellRenderer.INDICATION_FOCUS);
	private TextCellRenderer rowSpecialHeadRenderer = new TextCellRenderer(0) {
		@Override
		public void drawCell(org.eclipse.swt.graphics.GC gc, org.eclipse.swt.graphics.Rectangle rect, int col, int row, Object content, boolean focus, boolean fixed, boolean clicked, de.kupzog.ktable.KTableModel model)
		{
			super.drawCell(gc, rect, col, row, content, focus, fixed, clicked, model);
			System.out.println("draw");
			Color c = gc.getBackground();
			gc.setBackground(new Color(null, 0, 0, 0));
			gc.fillRectangle(rect.x, rect.y, rect.width/2, 2);
			gc.setBackground(c);
		};
	};
	private TextCellRenderer colHeadRenderer = new TextCellRenderer(TextCellRenderer.STYLE_FLAT);
	private CheckableCellRenderer[] bodyRenderer = new CheckableCellRenderer[6];
	
	private Point cellSpecialBorder = null;
	
	private boolean bShowName = true;
	public DSMTableModel() {
		initialize();
		
		Color bgColors[] = new Color[]{new Color(null, 0xFF, 0xFF, 0xFF), new Color(null, 0xa0, 0xe4, 0x9c),
										new Color(null, 0xfb, 0xac, 0xae), new Color(null, 0xF9, 0xDE, 0x90),
										new Color(null, 0x9c, 0x9F, 0xd6), new Color(null, 0xCB, 0x8F, 0x3A)};
		for(int i=0; i<bodyRenderer.length; i++) {
			bodyRenderer[i] = new CheckableCellRenderer(DefaultCellRenderer.INDICATION_FOCUS | CheckableCellRenderer.SIGN_X);
			bodyRenderer[i].setBackground(bgColors[i]);
		}
		colHeadRenderer.setAlignment(SWTX.ALIGN_HORIZONTAL_CENTER | SWTX.ALIGN_VERTICAL_CENTER);
		groupRowHeadRenderer.setBackground(new Color(null, 0xFA, 0xE4, 0x66));
		setShowName(true);
	}

	@Override
	public int getFixedHeaderColumnCount() {
		// 고정시킬 열의 개수(선택불가)
		return 0;
	}

	@Override
	public int getFixedHeaderRowCount() {
		// 고정시킬 행의 개수(선택불가)
		return 1;
	}

	@Override
	public int getFixedSelectableColumnCount() {
		// 고정시킬 열의 개수(선택가능)
		return 1;
	}

	@Override
	public int getFixedSelectableRowCount() {
		// 고정시킬 행의 개수(선택가능)
		return 0;
	}

	@Override
	public int getRowHeightMinimum() {
		// 최소 row의 높이
		return 30;
	}

	@Override
	public boolean isColumnResizable(int col) {
		// 이름 열(index 0)만 조정가능
		return col == 0;
	}

	@Override
	public boolean isRowResizable(int row) {
		return false;
	}

	@Override
	public KTableCellEditor doGetCellEditor(int col, int row) {
		if(col == 0 || row == 0)
			return null;

		if(col == row)
			return null;

		return new KTableCellEditorCheckbox();
	}

	@Override
	public KTableCellRenderer doGetCellRenderer(int col, int row) {
		if(col == 0) {
			if(cellSpecialBorder != null && col == cellSpecialBorder.x && row == cellSpecialBorder.y) {
				System.out.println("special renderer found");
				return rowSpecialHeadRenderer;
			}
			if(row == 0 || arrayList.get(row-1).isLeaf())
				return rowHeadRenderer;
			else
				return groupRowHeadRenderer;
		}
		if(row == 0)
			return colHeadRenderer;
		
		RowControl row1 = arrayList.get(row-1);
		RowControl row2 = arrayList.get(col-1);
		if(row1.getDepth() > row2.getDepth()) {
			while(row1.getDepth() != row2.getDepth()) {
				row1 = (RowControl) row1.getParent();
			}
		}
		else {
			while(row1.getDepth() != row2.getDepth()) {
				row2 = (RowControl) row2.getParent();
			}
		}
		
		while(row1 != row2) {
			row1 = (RowControl) row1.getParent();
			row2 = (RowControl) row2.getParent();
		}
		
		if(row1 == null) {
			System.out.println(String.format("strange... %s, %s", arrayList.get(row-1).getName(), arrayList.get(col-1).getName()));
			return null;
		}

		if(row1.isLeaf())
			row1 = (RowControl) row1.getParent();
		
		int depth = row1.getDepth();
		
		return bodyRenderer[depth%bodyRenderer.length];
	}

	@Override
	public int doGetColumnCount() {
		return (arrayList == null ? 0 : arrayList.size() + 1);
	}

	@Override
	public int doGetRowCount() {
		return (arrayList == null ? 0 : arrayList.size() + 1);
	}

	@Override
	public Object doGetContentAt(int col, int row) {
		if(arrayList == null)
			return "";
		
		if(col == 0 && row == 0)
			return "";
		
		if(col == 0)	// 이름
			return String.format("%d %s", row, bShowName ? arrayList.get(row-1).getName() : "");
		
		if(row == 0)	// 열번호
			return col;
		
		if(col == row)	// 별쓸모없는곳
			return false;
		
		if(arrayList.get(col-1).isLeaf() == false) {
			return ((GroupControl)arrayList.get(col-1)).isDependencyToChild(arrayList.get(row-1));
		}
		
		return depArray[row-1][col-1] == 1;
	}

	@Override
	public void doSetContentAt(int col, int row, Object value) {
		// do nothing
	}
	
	public void setContentAt(int col, int row, boolean value) throws Exception
	{
		// 실제 dependency 생성
		RowControl rcFrom = arrayList.get(row-1);
		RowControl rcTo = arrayList.get(col-1);
		if(rcFrom.isLeaf() && rcTo.isLeaf()) {
			if(value)
				rcFrom.setDependency(rcTo);
			else
				rcFrom.removeDependency(rcTo);
		}
		else {
			throw new Exception("cannot set dependency from or to group!");
		}
	}

	@Override
	public int getInitialColumnWidth(int col) {
		return 22;
	}

	@Override
	public int getInitialRowHeight(int row) {
		return 18;
	}
	
	@Override
	public void initialize() {
		super.initialize();
		this.arrayList = null;
		this.depArray = null;
	}
	
	public void setData(List<RowControl> list)
	{
		initialize();
		this.arrayList = list;
		
		if(list != null) {
			depArray = new int[arrayList.size()][arrayList.size()];
			for(int i=0; i<arrayList.size(); i++) {
				RowControl rcFrom = arrayList.get(i);
				
				for(int j=0; j<arrayList.size(); j++) {
					RowControl rcTo = arrayList.get(j);
					if(rcFrom.getDepenencyList().contains(rcTo)) {
						depArray[i][j] = 1;
					}
					else {
						depArray[i][j] = 0;
					}
				}
			}
		}
		else {
			depArray = null;
		}
	}
	
	@Override
	public String getTooltipAt(int col, int row) {
		if(col == row)
			return null;
		
		
		String strRet = null;
		if(col == 0) {
			strRet = String.format("%d %s", row, arrayList.get(row-1).getName());
		}
		else if(row == 0) {
			strRet = String.format("%d %s", col, arrayList.get(col-1).getName());
		}
		else if((boolean)getContentAt(col, row) == false) {
			// do nothing
		}
		else {
			strRet = String.format("%d %s -> %d %s", row, arrayList.get(row-1).getName(), col, arrayList.get(col-1).getName());	
		}
		return strRet;
	}

	public void setCellSpceialBorder(Point p) {
		this.cellSpecialBorder = p;
	}

	public Point getCellSpceialBorder() {
		return cellSpecialBorder;
	}
	
	public void setShowName(boolean bShow)
	{
		this.bShowName = bShow;
		if(bShow) {
			rowHeadRenderer.setAlignment(rowHeadRenderer.getAlignment() & ~SWTX.ALIGN_HORIZONTAL_CENTER | SWTX.ALIGN_HORIZONTAL_LEFT);
			groupRowHeadRenderer.setAlignment(rowHeadRenderer.getAlignment());
		}
		else {
			rowHeadRenderer.setAlignment(rowHeadRenderer.getAlignment() & ~SWTX.ALIGN_HORIZONTAL_LEFT | SWTX.ALIGN_HORIZONTAL_CENTER);
			groupRowHeadRenderer.setAlignment(rowHeadRenderer.getAlignment());
		}
	}

}
